package com.xhji.spider.controller;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.xhji.common.vo.Page;
import com.xhji.spider.entity.PageDetail;
import com.xhji.spider.entity.PageDetailRule;
import com.xhji.spider.mapper.PageDetailMapper;
import com.xhji.spider.mapper.PageDetailRuleMapper;
import com.xhji.spider.utils.StringUtil;
import com.xhji.spider.webmagic.pipeline.PageDetailCommonPipeline;
import com.xhji.spider.webmagic.pipeline.PageDetailModelPipeline;
import com.xhji.spider.webmagic.processor.PageDetailProcessor;
import com.xhji.web.mvc.validation.rules.Create;
import com.xhji.web.mvc.validation.rules.Update;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import tk.mybatis.mapper.entity.Example;
import us.codecraft.webmagic.ResultItems;
import us.codecraft.webmagic.Spider;

import javax.annotation.Resource;
import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Controller
@RequestMapping("/spider")
public class SpiderController {
    @Resource
    private PageDetailRuleMapper pageDetailRuleMapper;
    @Resource
    private PageDetailMapper pageDetailMapper;

    @RequestMapping("/rule/list")
    @ResponseBody
    public PageInfo<PageDetailRule> query(Page page) {
        Example example = new Example(PageDetailRule.class);
        example.setOrderByClause("id desc");
        return PageHelper.startPage(page).doSelectPageInfo(() -> pageDetailRuleMapper.selectByExample(example));
    }

    @RequestMapping("/rule/get")
    @ResponseBody
    @Validated
    public PageDetailRule get(@NotNull Integer id) {
        return pageDetailRuleMapper.selectByPrimaryKey(id);
    }

    @Validated(Create.class)
    @RequestMapping("/rule/insert")
    @ResponseBody
    public int addRule(@Valid PageDetailRule rule) {
        return pageDetailRuleMapper.insertSelective(rule);
    }

    @Validated(Update.class)
    @RequestMapping("/rule/update")
    @ResponseBody
    public int updateRule(@Valid PageDetailRule rule) {
        return pageDetailRuleMapper.updateByPrimaryKeySelective(rule);
    }

    @Validated
    @RequestMapping("/rule/delete")
    @ResponseBody
    public int deleteRule(@NotBlank String ids) {
        String[] split = ids.split(",");
        if (split.length == 1){
            return pageDetailRuleMapper.deleteByPrimaryKey(Integer.valueOf(split[0]));
        }else {
            return pageDetailRuleMapper.deleteByIdList(Stream.of(split).map(Integer::valueOf).collect(Collectors.toList()));
        }
    }

    @Resource
    private PageDetailModelPipeline pageDetailDaoPipeline;
    @Resource
    private PageDetailCommonPipeline pageDetailCommonPipeline;

    @RequestMapping("/rule/test")
    @ResponseBody
    @Validated
    public void test(@NotNull Integer id) {
        PageDetailRule rule = pageDetailRuleMapper.selectByPrimaryKey(id);
        handlerRule(rule);
        Spider spider = Spider.create(new PageDetailProcessor(rule)).thread(1);
        ResultItems resultItems = spider.get(rule.getStartUrl());
        PageDetail pageDetail = resultItems.get("pageDetail");
        System.out.println(JSON.toJSONString(pageDetail));
    }

    private void handlerRule(PageDetailRule rule){
        String helpUrlRegex = rule.getHelpUrlRegex();
        String targetUrlRegex = rule.getTargetUrlRegex();
        String startUrl = rule.getStartUrl();
        String domain = rule.getDomain();
        rule.setHelpUrlRegex(helpUrlRegex.startsWith(domain)?helpUrlRegex:domain+helpUrlRegex);
        rule.setTargetUrlRegex(targetUrlRegex.startsWith(domain)?targetUrlRegex:domain+targetUrlRegex);
        rule.setStartUrl(startUrl.startsWith(domain)?startUrl:domain+startUrl);
    }

    @RequestMapping("/rule/start")
    @ResponseBody
    @Validated
    public void start(@NotNull Integer id) {
        PageDetailRule rule = pageDetailRuleMapper.selectByPrimaryKey(id);
        handlerRule(rule);
        List<PageDetail> pageDetails = pageDetailMapper.select(PageDetail.builder().domain(rule.getDomain()).build());
        Set<String> set = pageDetails.stream().map(PageDetail::getUrl).collect(Collectors.toSet());
        Spider.create(new PageDetailProcessor(rule, set))
                .addUrl(Stream.of(rule.getStartUrl().split(",")).filter(StringUtils::hasText).map(StringUtil::encodeChinese).toArray(String[]::new))
                .addPipeline(pageDetailCommonPipeline)
                .thread(rule.getThreadCount() == null ? 1 : rule.getThreadCount())
                .run();
        //缺少终止方式
//        Spider spider = Spider.create(new PageDetailProcessor(rule))
//                .thread(rule.getThreadCount() == null ? 1 : rule.getThreadCount());
//        ResultItems resultItems = spider.<ResultItems>get(rule.getStartUrl());
//        PageDetail pageDetail = resultItems.<PageDetail>get("pageDetail");
//        System.out.println(JSON.toJSONString(pageDetail));
    }

    @RequestMapping("/detail/list")
    @ResponseBody
    public PageInfo<PageDetail> queryDetail(PageDetail pageDetail, Page page) {
        Example example = new Example(PageDetail.class);
        if (StringUtils.hasText(pageDetail.getDomain())){
            example.and().andLike("domain", "%" + pageDetail.getDomain() + "%");
        }
        example.setOrderByClause("id desc");
        return PageHelper.startPage(page).doSelectPageInfo(() -> pageDetailMapper.selectByExample(example));
    }

    @RequestMapping("/detail/get")
    @ResponseBody
    @Validated
    public PageDetail getDetail(@NotNull Integer id) {
        return pageDetailMapper.selectByPrimaryKey(id);
    }

    @Validated
    @RequestMapping("/detail/delete")
    @ResponseBody
    public int deleteDetail(@NotBlank String ids) {
        String[] split = ids.split(",");
        if (split.length == 1){
            return pageDetailMapper.deleteByPrimaryKey(Integer.valueOf(split[0]));
        }else {
            return pageDetailMapper.deleteByIdList(Stream.of(split).map(Integer::valueOf).collect(Collectors.toList()));
        }
    }
}
